package example.pattern.singleton;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class Main {
     static Set<Singleton1> set1 =  Collections.synchronizedSet(new HashSet<Singleton1>());
     static Set<Singleton2> set2 =  Collections.synchronizedSet(new HashSet<Singleton2>());
     static Set<Singleton3> set3 =  Collections.synchronizedSet(new HashSet<Singleton3>());
     static Set<NonSingleton> set4 =  Collections.synchronizedSet(new HashSet<NonSingleton>());
		
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ExecutorService es  = Executors.newFixedThreadPool(20);
		long time = System.currentTimeMillis();
		int loop = 100;
		for (int i = 0; i < loop; i++) {
			es.submit(new Task1());
		}
		es.shutdown();
		while(!es.isTerminated()){}
		System.out.println("---Task1 executed: " + (System.currentTimeMillis() - time) + "ms, counter : " + Task1.a.get());
		System.out.println("Set1 size: " + set1.size());
		
		es  = Executors.newFixedThreadPool(20);
		time = System.currentTimeMillis();
		for (int i = 0; i < loop; i++) {
			es.submit(new Task2());
		}
		es.shutdown();
		while(!es.isTerminated()){}
		System.out.println("---Task2 executed: " + (System.currentTimeMillis() - time) + "ms, counter : " + Task2.a.get());
		System.out.println("Set2 size: " + set2.size());
		
		es  = Executors.newFixedThreadPool(20);
		time = System.currentTimeMillis();
		for (int i = 0; i < loop; i++) {
			es.submit(new Task3());
		}
		es.shutdown();
		while(!es.isTerminated()){}
		System.out.println("---Task3 executed: " + (System.currentTimeMillis() - time) + "ms, counter : " + Task3.a.get());
		System.out.println("Set3 size: " + set3.size());
		
		es  = Executors.newFixedThreadPool(20);
		time = System.currentTimeMillis();
		for (int i = 0; i < loop; i++) {
			es.submit(new Task4());
		}
		es.shutdown();
		while(!es.isTerminated()){}
		System.out.println("---Task4 executed: " + (System.currentTimeMillis() - time) + "ms, counter : " + Task4.a.get());
		System.out.println("Set4 size: " + set4.size());
	}
	
	
	private static class Task1 implements Callable<Void>{
		public static AtomicInteger a = new AtomicInteger(0);
		@Override
		public Void call() throws Exception {
			set1.add(Singleton1.getInstance());
			a.getAndIncrement();
			return null;
		}
	}
	

	private static class Task2 implements Callable<Void>{
		public static AtomicInteger a = new AtomicInteger(0);
		@Override
		public Void call() throws Exception {
			set2.add(Singleton2.getInstance());
			a.getAndIncrement();
			return null;
		}
	}
	

	private static class Task3 implements Callable<Void>{
		public static AtomicInteger a = new AtomicInteger(0);
		@Override
		public Void call() throws Exception {
			set3.add(Singleton3.getInstance());
			a.getAndIncrement();
			return null;
		}
	}
	
	private static class Task4 implements Callable<Void>{
		public static AtomicInteger a = new AtomicInteger(0);
		
		@Override
		public Void call() throws Exception {
			set4.add(NonSingleton.newInstance());
			a.getAndIncrement();
			return null;
		}
	}

}
